home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: fat.c Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org> This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <ctype.h> /* toupper */ #include <string.h> #include <stdlib.h> #include <time.h> #include "types.h" #include "common.h" #include "fat.h" #include "lang.h" #include "fnctdsk.h" #include "testdisk.h" #include "intrface.h" static int set_FAT_info(t_param_disk *disk_car, const struct fat_boot_sector *fat_header, t_diskext *partition,const int debug); int dump_fat_rapport(const struct fat_boot_sector*fh1, const upart_type_t upart_type) { ecrit_rapport("sector_size %u\n", sector_size(fh1)); ecrit_rapport("cluster_size %u\n", fh1->cluster_size); ecrit_rapport("reserved %u\n", le16(fh1->reserved)); ecrit_rapport("fats %u\n", fh1->fats); ecrit_rapport("dir_entries %u\n", get_dir_entries(fh1)); ecrit_rapport("sectors %u\n", sectors(fh1)); ecrit_rapport("media %02X\n", fh1->media); ecrit_rapport("fat_length %u\n", le16(fh1->fat_length)); ecrit_rapport("secs_track %u\n", le16(fh1->secs_track)); ecrit_rapport("heads %u\n", le16(fh1->heads)); ecrit_rapport("hidden %u\n", le32(fh1->hidden)); ecrit_rapport("total_sect %u\n", le32(fh1->total_sect)); if(upart_type==UP_FAT32) { ecrit_rapport("fat32_length %u\n", le32(fh1->fat32_length)); ecrit_rapport("flags %04X\n", le16(fh1->flags)); ecrit_rapport("version %u.%u\n", fh1->version[0], fh1->version[1]); ecrit_rapport("root_cluster %u\n", le32(fh1->root_cluster)); ecrit_rapport("info_sector %u\n", le16(fh1->info_sector)); ecrit_rapport("backup_boot %u\n", le16(fh1->backup_boot)); ecrit_rapport("free_count %lu\n",get_free_count((const unsigned char*)fh1)); ecrit_rapport("next_free %lu\n",get_next_free((const unsigned char*)fh1)); } return 0; } int dump_fat_info(const struct fat_boot_sector*fh1, const upart_type_t upart_type) { switch(upart_type) { case UP_FAT12: wdoprintf(stdscr,"FAT : 12\n"); break; case UP_FAT16: wdoprintf(stdscr,"FAT : 16\n"); break; case UP_FAT32: wdoprintf(stdscr,"FAT : 32\n"); break; default: wdoprintf(stdscr,"Not a FAT\n"); return 0; } wdoprintf(stdscr,"cluster_size %u\n", fh1->cluster_size); wdoprintf(stdscr,"reserved %u\n", le16(fh1->reserved)); if(sectors(fh1)!=0) wdoprintf(stdscr,"sectors %u\n", sectors(fh1)); if(le32(fh1->total_sect)!=0) wdoprintf(stdscr,"total_sect %u\n", le32(fh1->total_sect)); if(upart_type==UP_FAT32) { wdoprintf(stdscr,"fat32_length %u\n", le32(fh1->fat32_length)); wdoprintf(stdscr,"root_cluster %u\n", le32(fh1->root_cluster)); wdoprintf(stdscr,"flags %04X\n", le16(fh1->flags)); wdoprintf(stdscr,"version %u.%u\n", fh1->version[0], fh1->version[1]); wdoprintf(stdscr,"root_cluster %u\n", le32(fh1->root_cluster)); wdoprintf(stdscr,"info_sector %u\n", le16(fh1->info_sector)); wdoprintf(stdscr,"backup_boot %u\n", le16(fh1->backup_boot)); wdoprintf(stdscr,"free_count %lu\n",get_free_count((const unsigned char*)fh1)); wdoprintf(stdscr,"next_free %lu\n",get_next_free((const unsigned char*)fh1)); } else { wdoprintf(stdscr,"fat_length %u\n", le16(fh1->fat_length)); wdoprintf(stdscr,"dir_entries %u\n", get_dir_entries(fh1)); } return 0; } int dump_2fat_info(const struct fat_boot_sector*fh1, const struct fat_boot_sector*fh2, const upart_type_t upart_type) { switch(upart_type) { case UP_FAT12: wdoprintf(stdscr,"FAT : 12\n"); break; case UP_FAT16: wdoprintf(stdscr,"FAT : 16\n"); break; case UP_FAT32: wdoprintf(stdscr,"FAT : 32\n"); break; default: wdoprintf(stdscr,"Not a FAT\n"); return 0; } wdoprintf(stdscr,"cluster_size %u %u\n", fh1->cluster_size, fh2->cluster_size); wdoprintf(stdscr,"reserved %u %u\n", le16(fh1->reserved),le16(fh2->reserved)); if(sectors(fh1)!=0 || sectors(fh2)!=0) wdoprintf(stdscr,"sectors %u %u\n", sectors(fh1), sectors(fh2)); if(le32(fh1->total_sect)!=0 || le32(fh2->total_sect)!=0) wdoprintf(stdscr,"total_sect %u %u\n", le32(fh1->total_sect), le32(fh2->total_sect)); if(upart_type==UP_FAT32) { wdoprintf(stdscr,"fat32_length %u %u\n", le16(fh1->fat32_length), le16(fh2->fat32_length)); wdoprintf(stdscr,"root_cluster %u %u\n", le32(fh1->root_cluster), le32(fh2->root_cluster)); /* wdoprintf(stdscr,"free_count %lu %lu\n",get_free_count((const unsigned char*)fh1),get_free_count((const unsigned char*)fh2)); wdoprintf(stdscr,"next_free %lu %lu\n",get_next_free((const unsigned char*)fh1),get_next_free((const unsigned char*)fh2)); */ } else { wdoprintf(stdscr,"fat_length %u %u\n", le16(fh1->fat_length), le16(fh2->fat_length)); wdoprintf(stdscr,"dir_entries %u %u\n", get_dir_entries(fh1), get_dir_entries(fh2)); } return 0; } int dump_fat_info_rapport(const struct fat_boot_sector*fh1, const upart_type_t upart_type) { ecrit_rapport("cluster_size %u\n", fh1->cluster_size); ecrit_rapport("reserved %u\n", le16(fh1->reserved)); if(sectors(fh1)!=0) ecrit_rapport("sectors %u\n", sectors(fh1)); if(le32(fh1->total_sect)!=0) ecrit_rapport("total_sect %u\n", le32(fh1->total_sect)); if(upart_type==UP_FAT32) { ecrit_rapport("fat32_length %u\n", le32(fh1->fat32_length)); ecrit_rapport("root_cluster %u\n", le32(fh1->root_cluster)); ecrit_rapport("free_count %lu\n",get_free_count((const unsigned char*)fh1)); ecrit_rapport("next_free %lu\n",get_next_free((const unsigned char*)fh1)); } else { ecrit_rapport("fat_length %u\n", le16(fh1->fat_length)); ecrit_rapport("dir_entries %u\n", get_dir_entries(fh1)); } return 0; } int dump_2fat_rapport(const struct fat_boot_sector*fh1, const struct fat_boot_sector*fh2, const upart_type_t upart_type) { switch(upart_type) { case UP_FAT12: ecrit_rapport("\nFAT12"); break; case UP_FAT16: ecrit_rapport("\nFAT16"); break; case UP_FAT32: ecrit_rapport("\nFAT32"); break; default: return 1; } ecrit_rapport("\nsector_size %u %u", sector_size(fh1),sector_size(fh2)); ecrit_rapport("\ncluster_size %u %u", fh1->cluster_size,fh2->cluster_size); ecrit_rapport("\nreserved %u %u", le16(fh1->reserved),le16(fh2->reserved)); ecrit_rapport("\nfats %u %u", fh1->fats,fh2->fats); ecrit_rapport("\ndir_entries %u %u", get_dir_entries(fh1),get_dir_entries(fh2)); ecrit_rapport("\nsectors %u %u", sectors(fh1),sectors(fh2)); ecrit_rapport("\nmedia %02X %02X", fh1->media,fh2->media); ecrit_rapport("\nfat_length %u %u", le16(fh1->fat_length),le16(fh2->fat_length)); ecrit_rapport("\nsecs_track %u %u", le16(fh1->secs_track),le16(fh2->secs_track)); ecrit_rapport("\nheads %u %u", le16(fh1->heads),le16(fh2->heads)); ecrit_rapport("\nhidden %u %u", le32(fh1->hidden),le32(fh2->hidden)); ecrit_rapport("\ntotal_sect %u %u", le32(fh1->total_sect),le32(fh2->total_sect)); if(upart_type==UP_FAT32) { ecrit_rapport("\nfat32_length %u %u", le32(fh1->fat32_length),le32(fh2->fat32_length)); ecrit_rapport("\nflags %04X %04X", le16(fh1->flags),le16(fh2->flags)); ecrit_rapport("\nversion %u.%u %u.%u", fh1->version[0], fh1->version[1],fh2->version[0], fh2->version[1]); ecrit_rapport("\nroot_cluster %u %u", le32(fh1->root_cluster),le32(fh2->root_cluster)); ecrit_rapport("\ninfo_sector %u %u", le16(fh1->info_sector),le16(fh2->info_sector)); ecrit_rapport("\nbackup_boot %u %u", le16(fh1->backup_boot),le16(fh2->backup_boot)); ecrit_rapport("\nfree_count %lu %lu",get_free_count((const unsigned char*)fh1),get_free_count((const unsigned char*)fh2)); ecrit_rapport("\nnext_free %lu %lu",get_next_free((const unsigned char*)fh1),get_next_free((const unsigned char*)fh2)); } ecrit_rapport("\n"); return 0; } int check_FAT(t_param_disk *disk_car,t_diskext *partition,const int debug) { t_sector buffer; if(disk_car->read(disk_car,1, &buffer, partition->lba)!=0) { aff_buffer(BUFFER_ADD,msg_CHKFAT_RERR); ecrit_rapport(msg_CHKFAT_RERR); return 1; } if(test_FAT(disk_car,(const struct fat_boot_sector *)buffer,partition,debug,0)!=0) { if(debug!=0) { ecrit_rapport("\n\ntest_FAT()\n"); aff_part_rapport(disk_car,partition); dump_fat_rapport((const struct fat_boot_sector*)buffer, partition->upart_type); } return 1; } set_FAT_info(disk_car,(const struct fat_boot_sector *)buffer,partition,debug); /* aff_buffer(BUFFER_ADD,"Ok\n"); */ return 0; } static int set_FAT_info(t_param_disk *disk_car, const struct fat_boot_sector *fat_header, t_diskext *partition,const int debug) { partition->name[0]=0; switch(partition->upart_type) { case UP_FAT12: case UP_FAT16: set_part_name(partition,((const char*)fat_header)+FAT1X_PART_NAME,11); if(check_volume_name(partition->name,11)) partition->name[0]='\0'; break; case UP_FAT32: fat32_set_part_name(disk_car,partition,fat_header); break; default: ecrit_rapport("set_FAT_info unknown upart_type\n"); return 1; } return 0; } dword get_next_cluster(t_param_disk *disk_car,const t_diskext *partition, const upart_type_t upart_type,const int offset, const dword cluster) { /* Offset can be offset to FAT1 or to FAT2 */ /* ecrit_rapport("get_next_cluster(upart_type=%u,offset=%u,cluster=%u\n",upart_type,offset,cluster); */ switch(upart_type) { case UP_FAT12: { unsigned char buffer[0x400]; dword offset_s,offset_o; offset_s=(cluster+cluster/2)/SECTOR_SIZE; offset_o=(cluster+cluster/2)%SECTOR_SIZE; if(disk_car->read(disk_car,2, &buffer, partition->lba+offset+offset_s)!=0) { ecrit_rapport("\nget_next_cluster error"); return 0; } if((cluster&1)!=0) return le16((*((__u16*)&buffer[offset_o])))>>4; else return le16(*((__u16*)&buffer[offset_o]))&0x0FFF; } case UP_FAT16: { unsigned char buffer[SECTOR_SIZE]; __u16 *p16=(__u16*)&buffer; dword offset_s,offset_o; offset_s=cluster/256; offset_o=cluster%256; if(disk_car->read(disk_car,1, &buffer, partition->lba+offset+offset_s)!=0) { ecrit_rapport("\nget_next_cluster error"); return 0; } return le16(p16[offset_o]); } case UP_FAT32: { unsigned char buffer[SECTOR_SIZE]; __u32 *p32=(__u32*)&buffer; dword offset_s,offset_o; offset_s=cluster/128; offset_o=cluster%128; if(disk_car->read(disk_car,1, &buffer, partition->lba+offset+offset_s)!=0) { ecrit_rapport("\nget_next_cluster error"); return 0; } /* FAT32 used 28 bits, the 4 high bits are reserved * 0x00000000: free cluster * 0x0FFFFFF7: bad cluster * 0x0FFFFFF8+: EOC End of cluster * */ return le32(p32[offset_o])&0xFFFFFFF; } default: ecrit_rapport("fat.c get_next_cluster unknown fat type\n"); return 0; } } dword fat32_get_prev_cluster(t_param_disk *disk_car,const t_diskext *partition, const unsigned int fat_offset, const dword cluster, const dword no_of_cluster) { unsigned char buffer[SECTOR_SIZE]; __u32 *p32=(__u32*)&buffer; dword hd_offset=partition->lba+fat_offset; dword prev_cluster; for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++) { unsigned int offset_s,offset_o; offset_s=prev_cluster/128; offset_o=prev_cluster%128; if((offset_o==0)||(prev_cluster==2)) { if(disk_car->read(disk_car,1, &buffer, hd_offset++)!=0) { ecrit_rapport("fat32_get_prev_cluster error\n"); return 0; } } if((le32(p32[offset_o]) & 0xFFFFFFF) ==cluster) return prev_cluster; } return 0; } dword get_prev_cluster(t_param_disk *disk_car,const t_diskext *partition, const upart_type_t upart_type,const int offset, const dword cluster, const dword no_of_cluster) { dword prev_cluster; for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++) { if(get_next_cluster(disk_car,partition,upart_type,offset, prev_cluster)==cluster) return prev_cluster; } return 0; } int test_FAT(t_param_disk *disk_car,const struct fat_boot_sector *fat_header, t_diskext *partition,const int debug, const int dump_ind) { dword start_fat1,start_fat2,start_rootdir,start_data,no_of_cluster,fat_length,fat_length_calc,part_size,end_data; const char *buffer=(const char*)fat_header; if(debug>1) { ecrit_rapport("test_FAT\n"); aff_part_rapport(disk_car,partition); } if(le16(fat_header->marker)!=0xAA55) { aff_buffer(BUFFER_ADD,"test_FAT : Boot sector doesn't have the endmark 0xAA55\n"); ecrit_rapport("test_FAT : Boot sector doesn't have the endmark 0xAA55\n"); return 1; } if(dump_ind!=0) dump(stdscr,fat_header,SECTOR_SIZE); if(!((fat_header->ignored[0]==0xeb && fat_header->ignored[2]==0x90)||fat_header->ignored[0]==0xe9)) { aff_buffer(BUFFER_ADD,msg_CHKFAT_BAD_JUMP); ecrit_rapport(msg_CHKFAT_BAD_JUMP); return 1; } if(sector_size(fat_header)!=SECTOR_SIZE) { aff_buffer(BUFFER_ADD,msg_CHKFAT_BYTESECT); ecrit_rapport(msg_CHKFAT_BYTESECT); return 1; } switch(fat_header->cluster_size) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: break; default: aff_buffer(BUFFER_ADD,msg_CHKFAT_SECT_CLUSTER); ecrit_rapport(msg_CHKFAT_SECT_CLUSTER); return 1; } if(fat_header->fats!=2) { aff_buffer(BUFFER_ADD,msg_CHKFAT_NBRFAT); ecrit_rapport(msg_CHKFAT_NBRFAT); return 1; } if(fat_header->media!=0xF8) { /* Legal values are 0xF0, 0xF8-0xFF but the only value I have ever seen is 0xF8 */ aff_buffer(BUFFER_ADD,msg_CHKFAT_MEDIA); ecrit_rapport(msg_CHKFAT_MEDIA); return 1; } fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length); part_size=(sectors(fat_header)>0?sectors(fat_header):fat_header->total_sect); start_fat1=le16(fat_header->reserved); start_fat2=start_fat1+fat_length; start_data=start_fat2+fat_length+(get_dir_entries(fat_header)*32+SECTOR_SIZE-1)/SECTOR_SIZE; no_of_cluster=(part_size-start_data)/fat_header->cluster_size; end_data=start_data+no_of_cluster*fat_header->cluster_size-1; if(no_of_cluster<4085) { if(debug) ecrit_rapport("FAT12\n"); if(sectors(fat_header)==0) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SIZE); ecrit_rapport(msg_CHKFAT_SIZE); } if(le16(fat_header->reserved)!=1) { aff_buffer(BUFFER_ADD,msg_CHKFAT_RESERV); ecrit_rapport(msg_CHKFAT_RESERV); return 1; } if((get_dir_entries(fat_header)==0)||(get_dir_entries(fat_header)%16!=0)) { aff_buffer(BUFFER_ADD,msg_CHKFAT_ENTRY); ecrit_rapport(msg_CHKFAT_ENTRY); return 1; } if((le16(fat_header->fat_length)>256)||(le16(fat_header->fat_length)==0)) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SECTPFAT); ecrit_rapport(msg_CHKFAT_SECTPFAT); return 1; } start_rootdir=start_fat2+fat_length; fat_length_calc=((no_of_cluster+2+SECTOR_SIZE*2/3-1)*3/2/SECTOR_SIZE); partition->upart_type=UP_FAT12; if(memcmp(buffer+FAT_NAME1,"FAT12 ",8)!=0) /* 2 Mo max */ { aff_buffer(BUFFER_ADD,"Should be marked as FAT12\n"); ecrit_rapport("Should be marked as FAT12\n"); } } else if(no_of_cluster<65525) { if(debug) ecrit_rapport("FAT16\n"); if(le16(fat_header->reserved)!=1) { aff_buffer(BUFFER_ADD,msg_CHKFAT_RESERV); ecrit_rapport(msg_CHKFAT_RESERV); return 1; } if(le16(fat_header->fat_length)==0) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SECTPFAT); ecrit_rapport(msg_CHKFAT_SECTPFAT); return 1; } if((get_dir_entries(fat_header)==0)||(get_dir_entries(fat_header)%16!=0)) { aff_buffer(BUFFER_ADD,msg_CHKFAT_ENTRY); ecrit_rapport(msg_CHKFAT_ENTRY); return 1; } start_rootdir=start_fat2+fat_length; fat_length_calc=((no_of_cluster+2+SECTOR_SIZE/2-1)*2/SECTOR_SIZE); partition->upart_type=UP_FAT16; if(memcmp(buffer+FAT_NAME1,"FAT16 ",8)!=0) { aff_buffer(BUFFER_ADD,"Should be marked as FAT16\n"); ecrit_rapport("Should be marked as FAT16\n"); } } else { if(debug) ecrit_rapport("FAT32\n"); if(sectors(fat_header)!=0) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SIZE); ecrit_rapport(msg_CHKFAT_SIZE); return 1; } if(get_dir_entries(fat_header)!=0) { aff_buffer(BUFFER_ADD,msg_CHKFAT_ENTRY); ecrit_rapport(msg_CHKFAT_ENTRY); return 1; } if((fat_header->version[0]!=0) || (fat_header->version[1]!=0)) { aff_buffer(BUFFER_ADD,msg_CHKFAT_BADFAT32VERSION); ecrit_rapport(msg_CHKFAT_BADFAT32VERSION); } if((le32(fat_header->root_cluster)<2) ||(le32(fat_header->root_cluster)>=2+no_of_cluster)) { aff_buffer(BUFFER_ADD,"Bad root_cluster\n"); ecrit_rapport("Bad root_cluster\n"); return 1; } start_rootdir=start_data+(le32(fat_header->root_cluster)-2)*fat_header->cluster_size; fat_length_calc=((no_of_cluster+2+SECTOR_SIZE/4-1)*4/SECTOR_SIZE); partition->upart_type=UP_FAT32; if(memcmp(buffer+FAT_NAME2,"FAT32 ",8)!=0) { aff_buffer(BUFFER_ADD,"Should be marked as FAT32\n"); ecrit_rapport("Should be marked as FAT32\n"); } } if(partition->part_size>0) { if(part_size>partition->part_size) { ecrit_rapport("test_FAT size boot_sector %ld > partition %ld\n",part_size,partition->part_size); aff_buffer(BUFFER_ADD,msg_CHKFAT_SIZE); return 1; } else { if((debug>0) && (part_size!=partition->part_size)) ecrit_rapport("test_FAT size boot_sector %ld, partition %ld\n",part_size,partition->part_size); } } if(debug>0) { ecrit_rapport("FAT1 : %lu-%lu\n",start_fat1,start_fat1+fat_length-1); ecrit_rapport("FAT2 : %lu-%lu\n",start_fat2,start_fat2+fat_length-1); ecrit_rapport("start_rootdir : %lu",start_rootdir); if(partition->upart_type==UP_FAT32) ecrit_rapport(" root cluster : %u",le32(fat_header->root_cluster)); ecrit_rapport("\nData : %lu-%lu\n",start_data,end_data); ecrit_rapport("sectors : %lu\n",part_size); ecrit_rapport("cluster_size : %u\n",fat_header->cluster_size); ecrit_rapport("no_of_cluster : %lu (2 - %lu)\n", no_of_cluster,no_of_cluster+1); ecrit_rapport("fat_length %lu calculated %lu\n",fat_length,fat_length_calc); } if(fat_length<fat_length_calc) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SECTPFAT); return 1; } comp_FAT(disk_car,partition,fat_length,le16(fat_header->reserved)); if(le16(fat_header->secs_track)!=disk_car->CHS.sector) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SECTTRACK); ecrit_rapport("sect/track %u (FAT)!= %u (HD)\n",le16(fat_header->secs_track),disk_car->CHS.sector); return 1; } if(le16(fat_header->heads)!=disk_car->CHS.head+1) { aff_buffer(BUFFER_ADD,msg_CHKFAT_SIDE); ecrit_rapport("heads/cylinder %u (FAT) != %u (HD)\n",le16(fat_header->heads),disk_car->CHS.head+1); return 1; } return 0; } int comp_FAT(t_param_disk *disk_car,const t_diskext *partition,const dword taille,const dword sect_res) { /* return 0 if FATs match */ unsigned int reste=taille; unsigned int read_size; unsigned char buffer[NBR_SECT*SECTOR_SIZE],buffer2[NBR_SECT*SECTOR_SIZE]; dword hd_offset, hd_offset2; hd_offset=partition->lba+sect_res; hd_offset2=hd_offset+taille; if(reste>1000) reste=1000; /* Quick check ! */ while(reste) { read_size=reste>NBR_SECT?NBR_SECT:reste; reste-=read_size; if(disk_car->read(disk_car,read_size, &buffer, hd_offset)) { ecrit_rapport(msg_CHKFAT_RERR); return 1;} if(disk_car->read(disk_car,read_size, &buffer2, hd_offset2)) { ecrit_rapport(msg_CHKFAT_RERR); return 1;} if(memcmp(buffer,buffer2,SECTOR_SIZE*read_size)!=0) { ecrit_rapport("FAT differs, FAT sectors=%lu-%lu/%lu\n", (unsigned long) (hd_offset-(partition->lba+sect_res)), (unsigned long) (hd_offset-(partition->lba+sect_res)+read_size), taille); return 1; } hd_offset+=read_size; hd_offset2+=read_size; } return 0; } unsigned int sector_size(const struct fat_boot_sector *fat_header) { return (fat_header->sector_size[1]<<8)+fat_header->sector_size[0]; } unsigned int get_dir_entries(const struct fat_boot_sector *fat_header) { return (fat_header->dir_entries[1]<<8)+fat_header->dir_entries[0]; } unsigned int sectors(const struct fat_boot_sector *fat_header) { return (fat_header->sectors[1]<<8)+fat_header->sectors[0]; } dword get_free_count(const unsigned char *boot_fat32) { return (boot_fat32[0x3E8+3]<<24)+(boot_fat32[0x3E8+2]<<16)+(boot_fat32[0x3E8+1]<<8)+boot_fat32[0x3E8]; } dword get_next_free(const unsigned char *boot_fat32) { return (boot_fat32[0x3EC+3]<<24)+(boot_fat32[0x3EC+2]<<16)+(boot_fat32[0x3EC+1]<<8)+boot_fat32[0x3EC]; } int recover_FAT12(t_param_disk *disk_car,const struct fat_boot_sector*fat_header, t_diskext *partition, const int debug, const int dump_ind) { const char*buffer=(const char*)fat_header; if(le16(fat_header->marker)==0xAA55) { if(memcmp(buffer+FAT_NAME1,"FAT12",5)==0) /* 2 Mo max */ { if(debug||dump_ind) { ecrit_rapport("\nFAT12 at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba)); } if(test_FAT(disk_car, fat_header, partition, debug, dump_ind)) return 1; partition->part_size=sectors(fat_header); partition->part_type=P_12FAT; /* partition->upart_type=UP_FAT12; already done in test_FAT */ if(buffer[38]==0x29) /* BS_BootSig */ { set_part_name(partition,buffer+FAT1X_PART_NAME,11); if(check_volume_name(partition->name,11)) partition->name[0]='\0'; } return 0; } } /* fin marqueur de fin :)) */ return 1; } int recover_FAT16(t_param_disk *disk_car,const struct fat_boot_sector*fat_header, t_diskext *partition, const int debug, const int dump_ind) { const char*buffer=(const char*)fat_header; if(le16(fat_header->marker)==0xAA55) { if(memcmp(buffer+FAT_NAME1,"FAT16",5)==0) { if(debug||dump_ind) { ecrit_rapport("\nFAT16 at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba)); } if(test_FAT(disk_car, fat_header, partition, debug, dump_ind)) return 1; if(sectors(fat_header)!=0) { partition->part_size=sectors(fat_header); partition->part_type=P_16FAT; } else { partition->part_size=le32(fat_header->total_sect); if(LBA2cylinder(disk_car,partition->lba+partition->part_size-1)<=1024) partition->part_type=P_16FATBD; else partition->part_type=P_16FATBD_LBA; } /* partition->upart_type=UP_FAT16; already done in test_FAT */ if(buffer[38]==0x29) /* BS_BootSig */ { set_part_name(partition,buffer+FAT1X_PART_NAME,11); if(check_volume_name(partition->name,11)) partition->name[0]='\0'; } return 0; } } /* fin marqueur de fin :)) */ return 1; } int recover_FAT32(t_param_disk *disk_car, const struct fat_boot_sector*fat_header, t_diskext *partition, const int debug, const int dump_ind,const int backup) { const char*buffer=(const char*)fat_header; if(le16(fat_header->marker)==0xAA55) { if(memcmp(buffer+FAT_NAME2,"FAT32",5)==0) { if(debug||dump_ind) { ecrit_rapport("\nFAT32 at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba)); } if(test_FAT(disk_car, fat_header, partition, debug, dump_ind)) return 1; if(sectors(fat_header)!=0) partition->part_size=sectors(fat_header); else partition->part_size=le32(fat_header->total_sect); if(LBA2cylinder(disk_car,partition->lba+partition->part_size-1)<=1024) partition->part_type=P_32FAT; else partition->part_type=P_32FAT_LBA; /* partition->upart_type=UP_FAT32; already done in test_FAT */ if(backup) { partition->boot_sector=6; partition->lba-=6; /* backup sector ... */ } fat32_set_part_name(disk_car,partition,fat_header); return 0; } } /* fin marqueur de fin =:-) */ return 1; } int fat32_set_part_name(t_param_disk *disk_car, t_diskext *partition, const struct fat_boot_sector*fat_header) { partition->name[0]='\0'; if((fat_header->cluster_size>0)&&(fat_header->cluster_size<=128)) { unsigned char *buffer=(unsigned char*)MALLOC(SECTOR_SIZE*fat_header->cluster_size); if(disk_car->read(disk_car,fat_header->cluster_size, buffer, partition->lba+le16(fat_header->reserved)+fat_header->fats*le32(fat_header->fat32_length)+(le32(fat_header->root_cluster)-2)*fat_header->cluster_size)) { ecrit_rapport(msg_ROOT_CLUSTER_RERR); } else { int i; for(i=0;(i<16*fat_header->cluster_size);i++) { /* Test attribut volume name and check if the volume name is erased or not */ if(((buffer[i*0x20+0xB] & ATTR_EXT) !=ATTR_EXT) && ((buffer[i*0x20+0xB] & ATTR_VOLUME) !=0) && (buffer[i*0x20]!=0xE5)) { /* dump(stdscr,&buffer[i*0x20],0x20); */ set_part_name(partition,&buffer[i*0x20],11); if(check_volume_name(partition->name,11)) partition->name[0]='\0'; } } } FREE(buffer); } if(partition->name[0]=='\0') { ecrit_rapport("set_FAT_info: name from BS used\n"); set_part_name(partition,((const char*)fat_header)+FAT32_PART_NAME,11); if(check_volume_name(partition->name,11)) partition->name[0]='\0'; } return 0; } int recover_HPFS(t_param_disk *disk_car,const struct fat_boot_sector*fat_header, t_diskext *partition, const int debug, const int dump_ind) { const char*buffer=(const char*)fat_header; if(le16(fat_header->marker)==0xAA55) { if(memcmp(buffer+OS2_NAME,"IBM",3)==0) { /* D'apres une analyse de OS2 sur systeme FAT... FAT_NAME1=FAT */ if(debug||dump_ind) { ecrit_rapport("\nHPFS maybe at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba)); } if(dump_ind) dump(stdscr,buffer,SECTOR_SIZE); if(sectors(fat_header)!=0) partition->part_size=sectors(fat_header); else partition->part_size=le32(fat_header->total_sect); partition->part_type=P_HPFS; partition->upart_type=UP_HPFS; return 0; } } /* fin marqueur de fin :)) */ return 1; } int recover_OS2MB(t_param_disk *disk_car, const struct fat_boot_sector*fat_header, t_diskext *partition, const int debug, const int dump_ind) { const char*buffer=(const char*)fat_header; if(le16(fat_header->marker)==0xAA55) { if(memcmp(buffer+FAT_NAME1,"FAT ",8)==0) { /* Attention a detecter apres OS2 */ if(debug||dump_ind) { ecrit_rapport("\nMarker (0xAA55) at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba)); } if(dump_ind) dump(stdscr,buffer,SECTOR_SIZE); partition->part_size=(disk_car->CHS.head+1) * disk_car->CHS.sector; /* 1 cylinder */ partition->part_type=P_OS2MB; partition->upart_type=UP_OS2MB; return 0; } } /* fin marqueur de fin :)) */ return 1; } int is_fat(const int part_type) { return (is_fat12(part_type)||is_fat16(part_type)||is_fat32(part_type)); } int is_fat12(const int part_type) { switch(part_type) { case P_12FAT: case P_12FATH: return 1; } return 0; } int is_fat16(const int part_type) { switch(part_type) { case P_16FAT: case P_16FATH: case P_16FATBD_LBA: case P_16FATBD: case P_16FATBDH: case P_16FATBD_LBAH: return 1; } return 0; } int is_fat32(const int part_type) { switch(part_type) { case P_32FAT: case P_32FAT_LBA: case P_32FATH: case P_32FAT_LBAH: return 1; } return 0; } int fat32_free_info(t_param_disk *disk_car,const t_diskext *partition, const unsigned int fat_offset, const dword no_of_cluster,dword *next_free,dword*free_count) { unsigned char buffer[SECTOR_SIZE]; __u32 *p32=(__u32*)&buffer; dword hd_offset=partition->lba+fat_offset; dword prev_cluster; *next_free=0; *free_count=0; for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++) { dword cluster; unsigned int offset_s,offset_o; offset_s=prev_cluster/128; offset_o=prev_cluster%128; if((offset_o==0)||(prev_cluster==2)) { if(disk_car->read(disk_car,1, &buffer, hd_offset++)!=0) { ecrit_rapport("fat32_get_prev_cluster error\n"); *next_free=0xFFFFFFFF; *free_count=0xFFFFFFFF; return 1; } } cluster=le32(p32[offset_o]) & 0xFFFFFFF; if(cluster==0) { (*free_count)++; if(*next_free==0) *next_free=prev_cluster; } } ecrit_rapport("next_free %ld, free_count %ld\n",*next_free,*free_count); return 0; }